#pragma once

#include "Strategy.h"
#include "MyStructures.h"
#include <vector>
#include <set>

using namespace model;
using namespace std;

enum Condition
{
	SAFE = 0,
	PATROL,
	UNBLOCK,
	MY_SHOOTING_RANGE,
	ENEMY_VISION_RANGE,
	THROW
};

struct CellSafeInfo
{
	vector<Trooper> lookers;
	const World *pworld;
	TrooperStance cellStance;

	CellSafeInfo () : lookers (), pworld (NULL), cellStance (UNKNOWN_STANCE) {}
	CellSafeInfo (vector<Trooper> Lookers, const World *world, TrooperStance CellStance) : lookers (Lookers), pworld (world), cellStance (CellStance) {}
};

struct CellPatrolInfo
{
	vector<Point> cellsToSee;
	const double range;
	const World *pworld;
	int currentDistanceGone;

	CellPatrolInfo () : cellsToSee (vector<Point> ()), range (0), pworld (NULL) {}
	CellPatrolInfo (vector<Point> CellsToSee, double Range, const World *world)
		: cellsToSee (CellsToSee), range (Range), pworld (world) {}
};

struct CellPathUnblockInfo
{
	vector<Point> pathToUnblock;
	set<Point> forbiddenPoints;

	CellPathUnblockInfo () {}
	CellPathUnblockInfo (vector<Point> PathToUnblock, set<Point> ForbiddenPoints)
		: pathToUnblock (PathToUnblock), forbiddenPoints (ForbiddenPoints) {}
};

struct CellMyShootingRangeInfo
{
	Point enemyLocation;
	double myShootingRange;
	const World *pworld;

	CellMyShootingRangeInfo () {}
	CellMyShootingRangeInfo (const Point& EnemyLocation, const double MyShootingRange, const World *world)
		: enemyLocation (EnemyLocation), myShootingRange (MyShootingRange), pworld (world) {}
};

struct CellEnemyVisionRangeInfo
{
	Point enemyLocation;
	double enemyVisionRange;
	const World *pworld;

	CellEnemyVisionRangeInfo () {}
	CellEnemyVisionRangeInfo (const Point& EnemyLocation, const double EnemyVisionRange, const World *world)
		: enemyLocation (EnemyLocation), enemyVisionRange (EnemyVisionRange), pworld (world) {}
};

struct CellThrowGrenageInfo
{
	vector<Trooper> enemies;
	const Game *pgame;
	Trooper foo;

	CellThrowGrenageInfo () {}
	CellThrowGrenageInfo (const vector<Trooper>& Enemies, const Game *game, Trooper& Foo)
		: enemies (Enemies), pgame (game), foo (Foo) {}
};

class CellChecker
{
private:
	CellSafeInfo cellSafeInfo;
	CellPathUnblockInfo cellPathUnblockInfo;
	CellMyShootingRangeInfo cellMyShootingRangeInfo;
	CellEnemyVisionRangeInfo cellEnemyVisionRangeInfo;
	CellThrowGrenageInfo cellThrowGrenageInfo;

	bool IsSafe (const Point& p);
	bool AllIsSeen (const Point& p);
	bool NotInPath (const Point& p);
	bool InMyRange (const Point& p);
	bool InEnemyRange (const Point& p);
	bool GrenadeReachable (const Point& p);

public:
	CellPatrolInfo cellPatrolInfo;

	CellChecker (CellSafeInfo _cellSafeInfo) : cellSafeInfo (_cellSafeInfo) {}
	CellChecker (CellPatrolInfo _cellPatrolInfo) : cellPatrolInfo (_cellPatrolInfo) {}
	CellChecker (CellPathUnblockInfo _cellPathUnblockInfo) : cellPathUnblockInfo (_cellPathUnblockInfo) {}
	CellChecker (CellMyShootingRangeInfo _cellMyShootingRangeInfo) : cellMyShootingRangeInfo (_cellMyShootingRangeInfo) {}
	CellChecker (CellEnemyVisionRangeInfo _cellEnemyVisionRangeInfo) : cellEnemyVisionRangeInfo (_cellEnemyVisionRangeInfo) {}
	CellChecker (CellThrowGrenageInfo _cellThrowGrenageInfo) : cellThrowGrenageInfo (_cellThrowGrenageInfo) {}

	bool Check (const Point& p, Condition idx);
};
